import SqlUtil from "../../Storage/SqlUtil";
import { ExtendsLoad } from "../CCExtends";
/**扩展原型组件 */
@ExtendsLoad(Object)
export class ObjectBaseExtends {
    static getNew<T>(originalObj: T): T & Object {
        return originalObj;
    }

    /** * 深拷贝 */
    static clonDeepObj<T>(originalObj: T): T {
        let clone = (target: any) => {
            if (target == null || typeof target !== 'object') {
                return null;
            }
            let result = null;
            if (target instanceof Date) {
                result = new Date();
                result.setTime(target.getTime());
                return result;
            }
            if (target instanceof Array) {
                result = [];
                for (let i = 0, length = target.length; i < length; i++) {
                    result[i] = clone(target[i]);
                }
                return result;
            }
            if (target instanceof Object) {
                result = {};
                for (const key in target) {
                    if (target.hasOwnProperty(key)) {
                        result[key] = clone(target[key]);
                    }
                }
                return result;
            }
            console.warn(`不支持的类型：${result}`);
        }
        return clone(originalObj);
    }

    /**
     * 拷贝对象
     */
    static copyObj<T>(originalObj: T): T & Object {
        return JSON.parse(JSON.stringify(originalObj));
    }
    /**
    * 判断指定的值是否为对象
    * @param value 值
    */
    static isObject(value: any): boolean {
        var type = typeof value;
        return value != null && (type == 'object' || type == 'function');
    }

    /**获取类型判断 */
    static type(val) {
        let type = this.getVarType(val);
        return this.transTypeToStr(type);
    }

    /**类型转换 */
    static transTypeToStr(type: string) {
        return {
            isObj: type == 'Object',
            isFun: type == 'function',
            isNum: type == 'number',
            isBool: type == 'boolean',
            isStr: type == 'string',
            isArr: type == 'Array',
            isNull: type == 'Null',
            isNaN: type == 'NaN',
            isData: type == 'Date',
            isRegExp: type == 'RegExp',
            isError: type == 'Error',
            isInfinity: type == 'Infinity',
            isUndef: type == 'undefined',
            isMap: type == 'Map',
            isSet: type == 'Set',
        }
    }

    /**
     * 判断类型
     * @param val 要判断的值
     * @returns 类型
     */
    static getVarType(val): 'number' | 'string' | 'boolean' | 'Array' | 'Object' | 'function' | 'Null' |
        'Date' | 'RegExp' | 'Error' | 'NaN' | 'Infinity' | 'undefined' | "Map" | "Set" {

        var type = typeof val;
        // object需要使用Object.prototype.toString.call判断
        if (type === 'object') {
            var typeStr = Object.prototype.toString.call(val);
            // 解析[object String]
            typeStr = typeStr.split(' ')[1];
            type = typeStr.substring(0, typeStr.length - 1);
        } else if (type === 'number') {
            if (isNaN(val))
                return 'NaN';
            else if (Object.is(val, Infinity) || Object.is(val, -Infinity))
                return 'Infinity';
            else if (Object.is(val, undefined))
                return 'undefined';
        }
        return type as any;
    }

    /**
     * 将对象扁平化为单深度对象
     * @return 扁平化对象
     * @example 
     *  {a:1,b:[],c:{d:2, e:[1,2,3]}}  =>  {a: 1, c.d: 2, c.e.0: 1, c.e.1: 2, c.e.2: 3}
     */
    static flattenObject(valueObj: any) {
        let _flattenObj = (ob: any) => {
            let toReturn = {};
            for (let i in ob) {
                if (!ob.hasOwnProperty(i))
                    continue;
                if ((typeof ob[i]) == 'object') {
                    let flatObject = _flattenObj(ob[i]);
                    for (let x in flatObject) {
                        if (!flatObject.hasOwnProperty(x))
                            continue;
                        toReturn[i + '.' + x] = flatObject[x];
                    }
                } else {
                    toReturn[i] = ob[i];
                }
            }
            return toReturn;
        }
        return _flattenObj(valueObj);
    }


    /**
    * 深拷贝
    * @param source 源数据
    */
    // static clonDeepObj2<T>(source: T): T {
    //     if (typeof source !== 'object' || source === null || source instanceof RegExp) {
    //         return source;
    //     }

    //     let result: any = null;
    //     if (Array.isArray(source)) {
    //         result = [];
    //         for (let item of source) {
    //             result.push(this.deepCopy(item));
    //         }
    //     } else {
    //         result = {};
    //         for (let key in source) {
    //             result[key] = this.deepCopy(source[key]);
    //         }
    //     }
    //     return result;
    // }

}

/**扩展组件 */
@ExtendsLoad(Object.prototype)
export class ObjectExtends {
    /**
      * 存储当前数组里的元素
      * @param saveStr 要保存的key
      * @param filterProps 要过滤的属性
      */
    static saveObj(saveStr: string, filterProps = []) {
        // console.time('SqlUtil.setItem');
        let filterObj = (this as any as Object).deepFilter(filterProps);
        let result = SqlUtil.setItem(saveStr, filterObj);
        // console.timeEnd('SqlUtil.setItem');
        return result;
    }

    /**
     * 从存储中加载指定字符的数据，并覆盖当前对应的元素
     * @param saveStr 要加载的key
     * @param def 默认值        
     * @returns 
     */
    static reloadObj(saveStr: string, def = {}) {
        try {
            let originalObj = this as any as Object;
            let getArr = SqlUtil.getItem(saveStr, def) as any;
            originalObj.margen(getArr);
            return true;
        } catch (error) {
            return false;
        }
    }

    /**
     * 查找指定的key 是否保存过
     * @param searchKey 要查找的key
     * @returns 
     */
    static isSave(searchKey: string) {
        return SqlUtil.hasItem(searchKey);
    }
    /**
     * 合并指定对象，该操作只会覆盖指定对象已有的值，不会删除其他属性
     * @param souresObj 指定对象
     */
    static margen(souresObj) {
        let originalObj = this as any as Object;
        let _assiginObj = (target = {}, sou = {}) => {
            let obj = target;
            let objType = Object.type(obj), souType = Object.type(sou);
            if ((objType.isFun || objType.isObj || objType.isArr) && (souType.isFun || souType.isObj || souType.isArr)) {
                for (let key in sou) {
                    // 如果target也存在 那就再次合并
                    if (target.hasOwnProperty(key)) {
                        obj[key] = _assiginObj(target[key], sou[key]);
                    } else {
                        // 不存在就直接添加
                        obj[key] = sou[key];
                    }
                }
                return obj;
            } else
                return sou; // 如果其中一个不是对象 就返回sources
        }
        _assiginObj(originalObj, souresObj);
    }

    /**
     * 深度遍历对象过滤指定对象(不改变原对象)
     * @param filterProps 要过滤的属性
     * @returns 
     */
    static deepFilter(filterProps = []) {
        let originalObj = this as any as Object;
        let filter = (obj: Object) => {
            let t = Object.type(obj);
            if (t.isObj || t.isFun) {
                let filterObj: Object = {};
                Object.keys(obj).forEach(key => {
                    if (!filterProps.includes(key)) {
                        let t = Object.type(obj[key]);
                        if (t.isObj) {
                            filterObj[key] = filter(obj[key]);
                        } else {
                            filterObj[key] = obj[key];
                        }
                    }
                });
                return filterObj;
            } else {
                return obj;
            }
        }
        let filterObj = filter(originalObj);
        return filterObj;
    }

    /**尝试转成数组，注意只处理了浅引用 */
    // static transArr() {
    //     let originalObj = this as any;
    //     let arr = [];

    //     return Array.from(originalObj) as any[];
    // }

    /**
     * 删除对象中的空值，null / undfined ，
     * @returns 没有空值的对象
     */
    static dealNull() {
        let originalObj = this as any;
        let del = {};
        for (let key of Object.keys(originalObj)) {
            if (originalObj[key] !== null && originalObj[key] !== undefined) {
                del[key] = originalObj[key];
            }
        }
        return del;
    }


    /**
     * 递归去除对象中所有空值，返回处理好的对象(注意改操作会修改当前对象的值，所以有proxy监听的要单独处理，不然可能会监听失效)
     * @returns 对象
     */
    static removeEmptyField() {
        let originalObj = this as any;
        let removeEmptyField = (dealObj) => {
            var newObj = {}
            if (typeof dealObj === 'string') {
                dealObj = JSON.parse(dealObj)
            }
            if (dealObj instanceof Array) {
                newObj = []
            }
            if (dealObj instanceof Object) {
                for (var attr in dealObj) {
                    // 属性值不为'',null,undefined才加入新对象里面(去掉'',null,undefined)
                    if (dealObj.hasOwnProperty(attr) && dealObj[attr] !== '' && dealObj[attr] !== null && dealObj[attr] !== undefined) {
                        if (dealObj[attr] instanceof Object) {
                            // 空数组或空对象不加入新对象(去掉[],{})
                            if (JSON.stringify(dealObj[attr]) === '{}' || JSON.stringify(dealObj[attr]) === '[]') {
                                continue
                            }
                            // 属性值为对象,则递归执行去除方法
                            newObj[attr] = removeEmptyField(dealObj[attr])
                        } else if (typeof dealObj[attr] === 'string' && (
                            (dealObj[attr].indexOf('{') > -1 && dealObj[attr].indexOf('}') > -1) ||
                            (dealObj[attr].indexOf('[') > -1 && dealObj[attr].indexOf(']') > -1)
                        )) {
                            // 属性值为JSON时
                            try {
                                var attrObj = JSON.parse(dealObj[attr])
                                if (attrObj instanceof Object) {
                                    newObj[attr] = removeEmptyField(attrObj)
                                }
                            } catch (e) {
                                newObj[attr] = dealObj[attr]
                            }
                        } else {
                            newObj[attr] = dealObj[attr]
                        }
                    }
                }
            }
            return newObj
        }
        return removeEmptyField(originalObj);
    }

    /**
     * 将对象扁平化为单深度对象
     * @return 扁平化对象
     * @example 
     *  {a:1,b:[],c:{d:2, e:[1,2,3]}}  =>  {a: 1, c.d: 2, c.e.0: 1, c.e.1: 2, c.e.2: 3}
     */
    static flattenObject() {
        let selfObj = this as object;
        let _flattenObj = (ob: any) => {
            let toReturn = {};
            for (let i in ob) {
                if (!ob.hasOwnProperty(i))
                    continue;
                if ((typeof ob[i]) == 'object') {
                    let flatObject = _flattenObj(ob[i]);
                    for (let x in flatObject) {
                        if (!flatObject.hasOwnProperty(x))
                            continue;
                        toReturn[i + '.' + x] = flatObject[x];
                    }
                } else {
                    toReturn[i] = ob[i];
                }
            }
            return toReturn;
        }
        return _flattenObj(selfObj);
    }
 
    /**
     * 获取对象属性的值（包括嵌套的对象值）
     * 如果没有嵌套属性（优化性能）
     * @param { attr } `attr` object key.
     * @return { any } Returns object value.
     * @example
     * let obj = {a:1,b:[],c:{d:2, e:[1,2,3]}};
     * getObjectValue("a") => 1;
     * getObjectValue("c.d") => 2;
     * getObjectValue("c.e.1") => 2;
     */
    static getObjectValue(attr: string) {
        let selfObj = this as object;
        if (attr.indexOf('.') === -1) {
            return selfObj[attr];
        } else { 
            return this.flattenObject()[attr];
        }
    }


}
